﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;
using DbSharp.Framework.Driver;
using DbSharp.Framework.TestEngine;

namespace DbSharp.Framework.DbObject
{


    public interface IStatementDeclaration
    {
        string Alias { get; set; }
        string Remark { get; set; }
        string ConnectionString { get; set; }
        string ConnectionProviderName { get; set; }
        string CommandText { get; }
        CommandType CommandType { get; }
        List<StatementArgument> ListArgument { get; set; }
        DbCommandExecuteType GetCommandExecuteType(ITestDataSource dataSource);
        StatementArgument FindArgument(string argumentName);
        IStatementDeclaration CloneStatement();
    }


    public static class StatementDeclarationExt
    {
        /// <summary>
        /// Normalize argument name to need the meet of the specific database server, e.g. prefix @ at the begin of the argument name
        /// </summary>
        /// <param name="argumentName"></param>
        /// <returns></returns>
        public static string NormalizeArgumentName(string providerName, string connectionString, string argumentName)
        {
            var testSource = RuntimeInfo.GetInstance().TestDataSourceFactory.SelectDbTestPlugin(providerName, connectionString);
            return testSource.NormalizeArgumentName(argumentName);
        }


        public static string NormalizeArgumentName(ITestDataSource testSource, string argumentName)
        { 
            return testSource.NormalizeArgumentName(argumentName);
        }

        public static bool FindByAlias(IStatementDeclaration x, string statementAlias)
        {
            string aliasName = statementAlias.Trim();
            if (string.Equals(aliasName, x.Alias.Trim(), StringComparison.OrdinalIgnoreCase))
                return true;
            else
                return false;
        }

        public static bool IsSqlStmtWithReturnValue(IStatementDeclaration statementDeclaration, out StatementArgument resultArg)
        {
            resultArg = null;
            foreach (var arg in statementDeclaration.ListArgument)
            {
                if (arg.IsSqlStmtResultArg)
                {
                    resultArg = arg;
                    return true;
                }
            }
            return false;
        }


        //In order to get all scalar style resultset, call DbCommandExecuteType.ExecuteReader rather than DbCommandExecuteType.ExecuteScalar
        //http://www.cnblogs.com/aspxphpjsprb/archive/2008/01/25/1052312.html
        public static DbCommandExecuteType DetermineDbCmdExecuteType(ITestDataSource testSource, List<StatementArgument> ListAllArgument)
        {
            List<StatementArgument> listOutRecordsetArgument = new List<StatementArgument>();
            List<StatementArgument> listOutScalarArgument = new List<StatementArgument>();

            foreach (var argument in ListAllArgument)
            {
                if (argument.Direction != ArgumentDirection.Input)
                {
                    if (testSource.IsRecordsetTypeArgument(argument.TypeStr))
                        listOutRecordsetArgument.Add(argument);
                    else
                        listOutScalarArgument.Add(argument);
                }
            }
            if (listOutRecordsetArgument.Count > 0)
                return DbCommandExecuteType.ExecuteReader;
            else if (listOutScalarArgument.Count > 0)
                return DbCommandExecuteType.ExecuteScalar;
            else
                return DbCommandExecuteType.ExecuteNoQuery;
        }
    }

}
